package com.twq.oo.classes

/**
 * Created by tangweiqun on 2017/11/27.
 * 1、scala中用class关键字来定义一个类
 */
class ChecksumAccumulator {
  //2、在类的定义中，我们可以放域和方法，我们称它们为成员
  //3、定义一个域，如果没有private的化则默认是public，
  // 但是为了程序的健壮性，需要防止内部域直接被外部访问，所以我们最好加上private
  private var sum = 0

  //注意：这个方法有side affect(副作用)，因为这个方法改变了方法外的变量的状态值
  //println()也是具有side affect的
  //我们称这个为方法，是因为它在一个类的里面，
  def add(b: Byte): Unit = {
    //b = 1 //4、编译将失败，因为方法中的参数都是val的
    sum += b
  }

  //5、对于简单的方法体，我们是可以省略点花括号{}
  //6、方法的返回值可以省略掉return，当然也可以加上，但是scala建议是省略掉
  //7、虽然方法可以推断出方法体的返回值的类型，但是最好是需要显示的声明返回类型，这样更具有可读性

  import ChecksumAccumulator._

  def checksum(): Int = ~(sum & CONSTANT) + 1

}

import scala.collection.mutable

/**
 * companion object(伴生对象)
 * 类和伴生对象可以互相访问私有成员
 * 我们可以将它认为就是一个对象，其类型是class的ChecksumAccumulator类型
 *
 * object中的方法和域和java中的static类似，一旦被访问就会初始化
 * 所以object中可以放：
 * 1、静态的工具方法
 * 2、静态的常量
 */
object ChecksumAccumulator {
  //这个私有常量可以只提供给伴生类使用
  private val CONSTANT = 0xFF

  private val cache = mutable.Map.empty[String, Int]

  def calculate(s: String): Int =
    if (cache.contains(s))
      cache(s)
    else {
      val acc = new ChecksumAccumulator
      //acc.sum //可以访问伴生类中的私有域
      for (c <- s)
        acc.add(c.toByte)
      val cs = acc.checksum()
      cache += (s -> cs)
      cs
    }
}


/**
 * standalone object(独立对象)
 *
 */
object Main {
  def main(args: Array[String]): Unit = {
    //需要说明的是：用val修饰对象的引用的时候，表明这个引用不能变，二这个对象的状态是可以变的
    val acc = new ChecksumAccumulator
    val csa = new ChecksumAccumulator

    List().foreach(i => println(i))

    //acc.sum = 3 //3、如果域被private修饰，则不能在外部访问
    //acc.sum = 8


    //访问object里的成员，可以直接根据object的名字然后调用成员
    ChecksumAccumulator.calculate("this is a first example")

    //伴生对象ChecksumAccumulator并不是伴生类ChecksumAccumulator的对象
    //checkSum(ChecksumAccumulator)
    //我们可以利用object来实现一个类的单例对象
    checkSum(SingletonChecksumAccumulator)
  }

  def checkSum(checksumAccumulator: ChecksumAccumulator): Int = {
    checksumAccumulator.add(1)
    checksumAccumulator.checksum()
  }

}


object SingletonChecksumAccumulator extends ChecksumAccumulator







